/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mycompany.delivery.web;

import com.mycompany.delivery.dto.AccountDTO;
import com.mycompany.delivery.dto.ContactDTO;
import com.mycompany.delivery.dto.DTOState;
import com.mycompany.delivery.dto.DeliveryDTO;
import com.mycompany.delivery.dto.UserDTO;
import com.mycompany.delivery.service.AccountCRUDServiceImpl;
import com.mycompany.delivery.service.AccountServiceImpl;
import com.mycompany.delivery.servicelayer.AccountCRUDService;
import com.mycompany.delivery.servicelayer.ContactService;
import com.mycompany.delivery.servicelayer.DeliveryService;
import com.mycompany.delivery.servicelayer.UserService;
import static com.mycompany.delivery.web.CourierController.log;
import java.util.Date;
import java.util.HashSet;
import java.util.Locale;
import javax.annotation.PostConstruct;
import javax.ejb.Local;
import javax.validation.Valid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.MessageSource;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.util.UriComponentsBuilder;

/**
 *
 * @author mhunek
 */
@Controller
@RequestMapping("/account")
public class AccountController {

    final static Logger log = LoggerFactory.getLogger(AccountController.class);
    /* @RequestMapping(value = {"/", "/hello**"}, method = RequestMethod.GET)
     public String welcomePage(Model model) {
     model.addAttribute("title", "Spring Security Custom Login Form");
     model.addAttribute("message", "This is welcome page!");
     return "/admin/hello";

     }*/

    @Autowired
    private MessageSource messageSource;

    @Autowired
    AccountCRUDService accService;

    @Autowired
    @Qualifier("accUserDetailsService")
    private AccountServiceImpl accUserDetailsService;

    @Autowired
    private ContactService contactService;

    @Autowired
    private UserService userService;

    @Autowired
    private DeliveryService deliveryService;

    @PostConstruct
    public void init() {
//základní accounty
        if (accService.findAccount("admin") == null) {
            AccountDTO acc1 = new AccountDTO();
            acc1.setEnabled(true);
            acc1.setLogin("admin");
            acc1.setPassword("admin");

            HashSet<String> roles = new HashSet<>();
            roles.add("ROLE_ADMIN");
            roles.add("ROLE_EMPL");
            roles.add("ROLE_COUR");
            acc1.setRoles(roles);
            accService.createAccount(acc1);
        }

        if (accService.findAccount("rest") == null) {
            AccountDTO acc1 = new AccountDTO();
            acc1.setEnabled(true);
            acc1.setLogin("rest");
            acc1.setPassword("rest");

            HashSet<String> roles = new HashSet<>();
            roles.add("ROLE_COUR");
            roles.add("ROLE_ADMIN");
            roles.add("ROLE_EMPL");
            acc1.setRoles(roles);
            accService.createAccount(acc1);
        }

        UserDetails userDetails = accUserDetailsService.loadUserByUsername("rest");
        Authentication authentication = new UsernamePasswordAuthenticationToken(
                userDetails, userDetails.getPassword(), userDetails.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authentication);

        if (accService.findAccount("user1") == null) {
            AccountDTO acc1 = new AccountDTO();
            acc1.setEnabled(true);
            acc1.setLogin("user1");
            acc1.setPassword("user1");

            HashSet<String> roles = new HashSet<>();
            roles.add("ROLE_EMPL");
            acc1.setRoles(roles);
            accService.createAccount(acc1);
        }

        if (accService.findAccount("user2") == null) {
            AccountDTO acc1 = new AccountDTO();
            acc1.setEnabled(true);
            acc1.setLogin("user2");
            acc1.setPassword("user2");

            HashSet<String> roles = new HashSet<>();
            roles.add("ROLE_COUR");
            acc1.setRoles(roles);
            accService.createAccount(acc1);
        }

        //Defaultní kontakty
        if (contactService.getAllContacts().size() < 2) {
            ContactDTO c1 = new ContactDTO(null, "Tomas", "Dvorak", "tmdvorka@gmail.com", "Praha", "ulice", "65464", "785476852");
            ContactDTO c2 = new ContactDTO(null, "Pavel", "Novak", "novak@gmail.com", "Praha", "ulice2", "65844", "785462452");
            contactService.create(c2);
            contactService.create(c1);
        }
        //Deafultní empl
        if (userService.getAllCouriers().size() < 1) {
            UserDTO cour1 = new UserDTO();
            cour1.setContact(contactService.getAllContacts().get(0));
            cour1.setLogin("courier1");
            userService.createCourier(cour1);
        }

        if (userService.getAllEmployees().size() < 1) {
            UserDTO empl = new UserDTO();
            empl.setContact(contactService.getAllContacts().get(0));
            empl.setLogin("empl");
            userService.createEmployee(empl);
        }

        if (deliveryService.getDeliveriesInUnprocessedState().size() < 1 || deliveryService.getDeliveriesInProcessedState().size() < 1) {
            DeliveryDTO del1 = new DeliveryDTO(DTOState.UNPROCESSED, contactService.getAllContacts().get(0), contactService.getAllContacts().get(1),new Date(), null, "notes", 500, false, null, null);
            DeliveryDTO del2 = new DeliveryDTO(DTOState.RECEIVEDBYCOURIER, contactService.getAllContacts().get(0), contactService.getAllContacts().get(1),new Date(), null, "notes2", 250, true,null, null);
            deliveryService.create(del2);
            deliveryService.create(del1);
            deliveryService.addDeliveryToEmployee(del2, userService.getAllEmployees().get(0));
            deliveryService.addDeliveryToEmployee(del1, userService.getAllEmployees().get(0));
            deliveryService.addDeliveryToCourier(del2, userService.getAllCouriers().get(0));

        }

    }

    @RequestMapping(value = "/admin**", method = RequestMethod.GET)
    public String adminPage(Model model) {
        return "/account/admin";

    }

    //Spring Security see this :
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public String login(
            @RequestParam(value = "error", required = false) String error,
            @RequestParam(value = "logout", required = false) String logout, Model model, Locale locale) {

        if (error != null) {
            model.addAttribute("error", messageSource.getMessage("account.logoutWrong", null, locale));
        }

        if (logout != null) {
            model.addAttribute("msg", messageSource.getMessage("account.logout", null, locale));

        }
        log.debug("check login");
        return "/account/login";

    }

    @RequestMapping(value = "/403", method = RequestMethod.GET)
    public String accesssDenied(Model model) {
        return "/account/403";

    }

    @RequestMapping(value = "/partlyVisible", method = RequestMethod.GET)
    public String partlyVisible(Model model) {

        return "/account/partlyVisible";

    }

    @RequestMapping(value = "/update/{name}", method = RequestMethod.GET)
    public String update_form(@PathVariable String name, Model model, RedirectAttributes redirectAttributes, UriComponentsBuilder uriBuilder, Locale locale) {
        UserDTO user = userService.findUserByLogin(name);

        AccountDTO account = new AccountDTO();
        log.debug("account size:" + account.getRoles().size());
        //dovol to založit učet jen někomu kdo existuje jako user/employee
        if (user != null) {
            account = accService.findAccount(user.getLogin());
            if (account == null) {
                account = new AccountDTO();
                account.setId(0l);
                account.setLogin(user.getLogin());
            }
            log.debug("account login:" + user.getLogin());

        } else {
            redirectAttributes.addFlashAttribute(
                    "message",
                    messageSource.getMessage("account.create.error.login", new Object[]{}, locale)
            );
            return "redirect:" + uriBuilder.path("/").build();
        }
        model.addAttribute("account", account);
        return "account/update";
    }

    /* @InitBinder
     protected void initBinder(WebDataBinder binder) {
     binder.addValidators(new AccountValidator());
     }*/
    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public String update(@RequestParam(required = false, value = "adm") String adm,
            @RequestParam(required = false, value = "empl") String empl, @RequestParam(required = false, value = "cour") String cour, @Valid @ModelAttribute AccountDTO acc, BindingResult bindingResult, Model model, RedirectAttributes redirectAttributes, UriComponentsBuilder uriBuilder, Locale locale) {
        log.debug("update(locale={}, courier={})", locale, acc);

        if (bindingResult.hasErrors()) {
            log.debug("binding errors");
            for (ObjectError ge : bindingResult.getGlobalErrors()) {
                log.debug("ObjectError: {}", ge);
            }
            for (FieldError fe : bindingResult.getFieldErrors()) {
                log.debug("FieldError: {}", fe);
            }
            model.addAttribute("account", acc);
            String mailmessage = messageSource.getMessage("account.validate.password", null, locale);
            model.addAttribute("message", mailmessage);
            return "account/update";
            //return acc.getId() == null ? "courier/list" : "courier/edit";
        }
        acc.setEnabled(true);
        if (adm != null) {
            HashSet<String> roles = new HashSet<>();
            roles.add("ROLE_ADMIN");
            roles.add("ROLE_EMPL");
            roles.add("ROLE_COUR");
            acc.setRoles(roles);
        } else if (empl != null) {
            HashSet<String> roles = new HashSet<>();
            roles.add("ROLE_EMPL");
            acc.setRoles(roles);
        } else {
            HashSet<String> roles = new HashSet<>();
            roles.add("ROLE_COUR");
            acc.setRoles(roles);
        }
        if (acc.getId() == null || acc.getId() == 0l) {

            accService.createAccount(acc);
            redirectAttributes.addFlashAttribute(
                    "message",
                    messageSource.getMessage("account.create.message", new Object[]{}, locale)
            );
        } else {
            accService.updateAccount(acc);
            redirectAttributes.addFlashAttribute(
                    "message",
                    messageSource.getMessage("account.edit.message", new Object[]{}, locale)
            );
        }
        return "redirect:" + uriBuilder.path("/").build();
    }
}
